Mobile development: Netstat, know your device’s open ports
On desktop PCs you have the nice tool netstat to see which ports are open on the PC. A customer wanted to know, why his devices do not release there internet connection. The only tool I know, that will show open network connections, is called netstat. Unfortunately I did not find such tool for Windows Mobile and so I wrote one myself:
netstat for windows mobile
NetstatCF2 is written in C#, Compact Framework. After you started the tool it immediately collects the open ports data. It will also log this data periodically (every 3 seconds) to a log file called “\netstat.log”.
The code makes massive calls to the ipHlp API functions. Here are some sample snippets:
...
public class IPHlpAPI32Wrapper
{
public const byte NO_ERROR = 0;
public const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
public const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
public const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
public int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS;
[DllImport("iphlpapi.dll", SetLastError = true)]
public extern static int GetUdpStatistics(ref MIB_UDPSTATS pStats);
[DllImport("iphlpapi.dll", SetLastError = true)]
public static extern int GetUdpTable(byte[] UcpTable, out int pdwSize, bool bOrder);
[DllImport("iphlpapi.dll", SetLastError = true)]
public extern static int GetTcpStatistics(ref MIB_TCPSTATS pStats);
[DllImport("iphlpapi.dll", SetLastError = true)]
public static extern int GetTcpTable(byte[] pTcpTable, out int pdwSize, bool bOrder);
[DllImport("iphlpapi.dll", SetLastError = true)]
public static extern int GetIpForwardTable(IntPtr pIpForwardTable, ref int pdwSize, bool bOrder);
[DllImport("iphlpapi.dll", SetLastError = true)]
public static extern int GetIpForwardTable(byte[] pIpForwardTable, ref int pdwSize, bool bOrder);
...
public void GetTcpConnexions()
{
byte[] buffer = new byte[20000]; // Start with 20.000 bytes left for information about tcp table
int pdwSize = 20000;
int res = IPHlpAPI32Wrapper.GetTcpTable(buffer, out pdwSize, true);
if (res != NO_ERROR)
{
buffer = new byte[pdwSize];
res = IPHlpAPI32Wrapper.GetTcpTable(buffer, out pdwSize, true);
if (res != 0)
return; // Error. You should handle it
}
TcpConnexion = new IpHlpApidotnet.MIB_TCPTABLE();
int nOffset = 0;
// number of entry in the
TcpConnexion.dwNumEntries = Convert.ToInt32(buffer[nOffset]);
nOffset += 4;
TcpConnexion.table = new MIB_TCPROW[TcpConnexion.dwNumEntries];
for (int i = 0; i < TcpConnexion.dwNumEntries; i++)
{
// state
int st = Convert.ToInt32(buffer[nOffset]);
// state in string
//((MIB_TCPROW)
(TcpConnexion.table[i]).StrgState = convert_state(st);
// state by ID
//((MIB_TCPROW)
(TcpConnexion.table[i]).iState = st;
nOffset += 4;
// local address
string LocalAdrr = buffer[nOffset].ToString() + "." + buffer[nOffset + 1].ToString() + "." + buffer[nOffset + 2].ToString() + "." + buffer[nOffset + 3].ToString();
nOffset += 4;
//local port in decimal
int LocalPort = (((int)buffer[nOffset]) << 8) + (((int)buffer[nOffset + 1])) +
(((int)buffer[nOffset + 2]) << 24) + (((int)buffer[nOffset + 3]) << 16);
nOffset += 4;
// store the remote endpoint
//((MIB_TCPROW)(
(TcpConnexion.table[i]).Local = new IPEndPoint(IPAddress.Parse(LocalAdrr), LocalPort);
// remote address
string RemoteAdrr = buffer[nOffset].ToString() + "." + buffer[nOffset + 1].ToString() + "." + buffer[nOffset + 2].ToString() + "." + buffer[nOffset + 3].ToString();
nOffset += 4;
// if the remote address = 0 (0.0.0.0) the remote port is always 0
// else get the remote port in decimal
int RemotePort;
//
if (RemoteAdrr == "0.0.0.0")
{
RemotePort = 0;
}
else
{
RemotePort = (((int)buffer[nOffset]) << 8) + (((int)buffer[nOffset + 1])) +
(((int)buffer[nOffset + 2]) << 24) + (((int)buffer[nOffset + 3]) << 16);
}
nOffset += 4;
//((MIB_TCPROW)
(TcpConnexion.table[i]).Remote = new IPEndPoint(IPAddress.Parse(RemoteAdrr), RemotePort);
}
}
...
public void GetUdpConnexions()
{
byte[] buffer = new byte[20000]; // Start with 20.000 bytes left for information about tcp table
int pdwSize = 20000;
int res = IPHlpAPI32Wrapper.GetUdpTable(buffer, out pdwSize, true);
if (res != NO_ERROR)
{
buffer = new byte[pdwSize];
res = IPHlpAPI32Wrapper.GetUdpTable(buffer, out pdwSize, true);
if (res != 0)
return; // Error. You should handle it
}
UdpConnexion = new IpHlpApidotnet.MIB_UDPTABLE();
int nOffset = 0;
// number of entry in the
UdpConnexion.dwNumEntries = Convert.ToInt32(buffer[nOffset]);
nOffset += 4;
UdpConnexion.table = new MIB_UDPROW[UdpConnexion.dwNumEntries];
for (int i = 0; i < UdpConnexion.dwNumEntries; i++)
{
string LocalAdrr = buffer[nOffset].ToString() + "." + buffer[nOffset + 1].ToString() + "." + buffer[nOffset + 2].ToString() + "." + buffer[nOffset + 3].ToString();
nOffset += 4;
int LocalPort = (((int)buffer[nOffset]) << 8) + (((int)buffer[nOffset + 1])) +
(((int)buffer[nOffset + 2]) << 24) + (((int)buffer[nOffset + 3]) << 16);
nOffset += 4;
//((MIB_UDPROW)
(UdpConnexion.table[i]).Local = new IPEndPoint(IPAddress.Parse(LocalAdrr), LocalPort);
}
}
...
public class IPHelper
{
private const int NO_ERROR = 0;
private const int MIB_TCP_STATE_CLOSED = 1;
private const int MIB_TCP_STATE_LISTEN = 2;
private const int MIB_TCP_STATE_SYN_SENT = 3;
private const int MIB_TCP_STATE_SYN_RCVD = 4;
private const int MIB_TCP_STATE_ESTAB = 5;
private const int MIB_TCP_STATE_FIN_WAIT1 = 6;
private const int MIB_TCP_STATE_FIN_WAIT2 = 7;
private const int MIB_TCP_STATE_CLOSE_WAIT = 8;
private const int MIB_TCP_STATE_CLOSING = 9;
private const int MIB_TCP_STATE_LAST_ACK = 10;
private const int MIB_TCP_STATE_TIME_WAIT = 11;
private const int MIB_TCP_STATE_DELETE_TCB = 12;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
...
But there is nothing special except on how to use C/C++ structures in C#.
Here is a sample of the logged data:
xxxxxxxxxxx AM ################# ======= TCP table ======== local remote 0.0.0.0: 21 0.0.0.0: 0 LISTEN 0.0.0.0: 1004 0.0.0.0: 0 LISTEN 0.0.0.0: 2188 0.0.0.0: 0 LISTEN 0.0.0.0: 2189 0.0.0.0: 0 LISTEN 0.0.0.0: 5655 0.0.0.0: 0 LISTEN 0.0.0.0: 52241 0.0.0.0: 0 LISTEN 127.0.0.1: 1032 127.0.0.1: 52241 ESTAB 127.0.0.1: 1034 127.0.0.1: 52241 ESTAB 127.0.0.1: 1035 127.0.0.1: 52241 ESTAB 127.0.0.1: 1036 127.0.0.1: 52241 ESTAB 127.0.0.1: 52241 127.0.0.1: 1032 ESTAB 127.0.0.1: 52241 127.0.0.1: 1034 ESTAB 127.0.0.1: 52241 127.0.0.1: 1035 ESTAB 127.0.0.1: 52241 127.0.0.1: 1036 ESTAB 192.168.55.101: 1082 192.168.55.100: 7438 ESTAB 192.168.55.101: 1083 192.168.55.100: 990 ESTAB 192.168.55.101: 1086 192.168.55.100: 990 ESTAB 192.168.55.101: 1087 192.168.55.100: 990 ESTAB 192.168.55.101: 1092 192.168.55.100: 990 ESTAB 192.168.55.101: 1102 192.168.55.100: 1004 ESTAB 192.168.55.101: 1103 192.168.55.100: 990 ESTAB 192.168.128.104: 1033 192.168.128.5: 62241 ESTAB 192.168.128.104: 5655 192.168.128.2: 59534 ESTAB 192.168.128.104: 5655 192.168.128.2: 59535 ESTAB 192.168.128.104: 6510 192.168.128.2: 59536 ESTAB 192.168.128.104: 6510 192.168.128.2: 59537 ESTAB ======= UDP table ======== 0.0.0.0: 53 0.0.0.0: 137 0.0.0.0: 138 0.0.0.0: 1088 0.0.0.0: 9204 0.0.0.0: 49111 192.168.128.104: 68 ======= TCP statistics ======== Retransmission timeout (min/max): Van Jacobson's Algorithm: 300/120000 max connnections: -1 active open: 69 passive open: 196 failed attempts: 0 established resets: 243 current established: 20 segments in: 134380 segments out: 130900 retransmitted segments: 175 in errors: 0 out resets: 861 num connections: 26 ======= UDP statistics ======== in datagrams: 13771 in errors: 0 num ports: 3353 num addresses: 7 out datagrams: 887 ======= Adapter infos ========== 131074: BCMCF1, 192.168.128.104 262147: USB Cable:, 192.168.55.101 ======= Route entries ========== Network Destination Netmask Gateway Interface Metric 0.0.0.0 0.0.0.0 192.168.55.101 003 0 225.20.0.0 0.0.0.0 255.255.255.255 255 0 0.0.0.0 0.0.0.0 192.168.128.1 002 0 225.20.0.0 0.0.0.0 255.255.255.255 255 0 127.0.0.0 255.0.0.0 127.0.0.1 001 0 104.148.1.0 0.0.0.0 255.255.255.255 255 0 192.168.55.101 255.255.255.255 127.0.0.1 001 0 225.20.0.0 0.0.0.0 255.255.255.255 255 0 192.168.55.255 255.255.255.255 192.168.55.101 003 0 225.20.0.0 0.0.0.0 255.255.255.255 255 0 192.168.128.0 255.255.255.0 192.168.128.104 002 0 67.148.1.0 0.0.0.0 255.255.255.255 255 0
Hopefully you use this small tool at a special time.
Code and sample bin at code.google.com (VS2008, CF2, WM5SDK)
Possibly outdated bin: [Download not found]




http://www.led-mg.de